import { computed, ref } from 'vue'
import qs from 'qs'
import { localStorage, sessionStorage } from 'mp-storage'
import { clearToken, refreshRequest, getToken } from '@U/Auth'
import { MsgLoadingClear } from '@C/Msg'
import type { IFunc, IObj } from '@/interface'
import request from '@/http/request'
import store from '@/store'
import { hasVarObject, hasVarString } from '@/interface'
import { Router } from '@/router/index'

// Vuex
export const storeState = computed(() => store?.state)?.value
export const storeCommit = (mutation: string, newVal?: any) => store.commit(mutation, newVal)

// Router
export { Router } from '@/router/index'

// Storage
export { localStorage, sessionStorage } from 'mp-storage'
export const LStorage = (key?: string, value?: string) => storage('local', key, value)
export const LStorageClear = (key?: string) => storage('local', key, '', true)
export const SStorage = (key?: string, value?: string) => storage('session', key, value)
export const SStorageClear = (key?: string) => storage('session', key, '', true)
// 吸底按钮底部安全距离
export const keepBottomSafeDis = () => ({ paddingBottom: `${storeState.bottomSafeDis}rpx` })
// 底部留出吸底按钮距离，防止遮盖内容
export const bottomStaySpace = () => ({ paddingBottom: `${storeState.bottomSafeDis + 108}rpx` })

function storage(mode: 'local' | 'session', key?: string, value?: string, clear?: boolean) {
    const _storage = {
        local: localStorage,
        session: sessionStorage,
    }[mode]
    if (clear) return key ? _storage.removeItem(key) : _storage.clear()
    if (key && value) return _storage.setItem(key, value)
    if (key) return _storage.getItem(key)
    const allStorage: IObj = {}
    _storage?.__keys?.forEach((key: string) => {
        allStorage[key] = _storage.getItem(key)
    })
    return allStorage
}

// Request
export const getReq = (url: string, params?: IObj): IObj => request({
    url,
    method: 'GET',
    data: params || {},
    header: {
        'content-type': 'application/x-www-form-urlencoded;charset=UTF-8',
    },
}).catch(err => {
    console.log(err)
})

export const postReq = (url: string, params?: IObj, contentType?: string): IObj => request({
    url,
    method: 'POST',
    data: params || {},
    transformRequest: [(params: IObj) => qs.stringify(params)],
    header: {
        'content-type': contentType || 'application/x-www-form-urlencoded;charset=UTF-8',
    },
}).catch(err => {
    console.log(err)
})

// 流式输出
export const streamOutput = (url: string, params?: IObj): IObj => new Promise(async (resolve, reject) => {
    const { code, data: refreshData } = await refreshRequest().finally(() => {})
    if (code === 200) {
        if (!refreshData) {
            clearToken()
            MsgLoadingClear({ icon: 'error', msg: '请重新登录' })
            setTimeout(() => Router.reLaunch('login'), 1500)
            return
        }
        const { token_type, access_token } = refreshData
        const token = `${ token_type } ${ access_token }`
        const response = uni.request({
            url: `${import.meta.env.VITE_APP_BASE_API}${url}`,
            method: 'POST',
            data: params || {},
            timeout: 600000,
            header: {
                Authorization: token,
            },
            responseType: 'text',
            enableChunked: true, // 开启流传输
            success: (res) => {
                resolve(res)
            },
            fail: (err) => {
                reject(err)
            },
        })
        // 返回请求的响应
        resolve(response)
    }
})
// 中断流式输出
export const abortRequest = (requestTask: any) => {
    if (requestTask) {
        // 调用abort()中断请求
        requestTask.abort()
        // 请求后置空
        requestTask = null
    }
}

export const getFileReq = (url: string, params?: IObj): IObj => request({
    url,
    method: 'GET',
    data: params || {},
    header: {
        'content-type': 'application/json',
    },
    responseType: 'arraybuffer',
})

export const postFileReq = async (url: string, filePath: string): Promise<IObj> => new Promise(async (resolve) => {
    const { code, data: refreshData } = await refreshRequest().finally(() => {})
    if (code === 200) {
        if (!refreshData) {
            clearToken()
            MsgLoadingClear({ icon: 'error', msg: '请重新登录' })
            setTimeout(() => Router.reLaunch('login'), 1500)
            return
        }
        const { token_type, access_token } = refreshData
        const token = `${ token_type } ${ access_token }`
        uni.uploadFile({
            url: `${/^http/.test(url) ? '' : import.meta.env.VITE_APP_BASE_API}${url || ''}`,
            header: {
                'content-type': 'multipart/form-data',
                'authorization': token,
            },
            timeout: 60000,
            name: 'files',
            filePath,
            success(res) {
                resolve(res)
            },
            fail(err) {
                console.log(err)
            },
        })
    }
})
// 自动检测CSS单位
export const hasUnit = (t: string | number) => {
    if (/\d$/.test(t.toString())) return `${t}rpx`
    return t
}

// uniapp 生命周期
export {
    // 页面加载，可以获取上个页面传递的参数
    onLoad,
    // 页面初次渲染完成
    onReady,
    // 页面显示
    onShow,
    // 页面隐藏
    onHide,
    // 页面卸载
    onUnload,
} from '@dcloudio/uni-app'

// 用户操作 分享，转发...
export {
    // 分享好友
    onShareAppMessage,
    // 转发到朋友圈
    onShareTimeline,
    // 收藏
    onAddToFavorites,
} from '@dcloudio/uni-app'

// 自适应背景图
export const autoBG = (path: string, base64?: boolean) => `url('${base64 ? 'data:image/png;base64,' : ''}${path}') no-repeat center/contain`
export const autoBGCover = (path: string, base64?: boolean) => `url('${base64 ? 'data:image/png;base64,' : ''}${path}') no-repeat center/cover`

// 字符限制显示字数
export const limitText = (text: string, number?: number) => {
    let _d = ''
    if (text.length > (number ?? 20)) {
        _d = `${text.substring(0, (number ?? 20)) }...`
        return _d
    }
    return text
}

// obj <=> query
export const obj_oto_query = (obj_or_query: IObj | string) => {
    let query = ''
    const obj: IObj = {}

    if (hasVarObject(obj_or_query)) {
        const obj_l = Object.keys(obj_or_query)
        obj_l.forEach((key: string, index: number) => {
            query += `${key}=${(obj_or_query as IObj)[key]}${index !== obj_l.length - 1 ? '&' : ''}`
        })
        return query
    }
    if (hasVarString(obj_or_query) && hasVarObject(JSON.parse(obj_or_query as string))) {
        return JSON.parse(obj_or_query as string)
    }
    if (hasVarString(obj_or_query)) {
        obj_or_query.split('&').forEach((pair: string) => {
            if (pair) {
                const _obj = pair.split('=')
                obj[_obj[0]] = _obj[1]
            }
        })
        return obj
    }
    return new Error('仅支持 NormalObject 与 String: HttpQuery 互相转化！')
}

// 日期转时间戳
export function dateToTimestamp(date: any) {
    const parts = date.split('-')
    const year = parseInt(parts[0], 10)
    const month = parseInt(parts[1], 10) - 1
    const day = parseInt(parts[2], 10)
    const dateObject = new Date(year, month, day)
    const timestamp = dateObject.getTime()
    return timestamp
}

    // 获取当天 凌晨 12：00 点时间戳
export function getMidnightTimestamp() {
    const now = new Date()
    const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0)
    return midnight.getTime()
    }

    // 获取月天数
    export function hasDayNum(year: any, month: any) {
    if (month < 1 || month > 12) {
        return
    }
    const dayInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    if (month === 2) {
        if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
        return 29
        }
        return 28
    }
    return dayInMonth[month - 1]
}

// 节流
export function throttle(callBack: IFunc, time = 250) {
    let canRun = true

    return (...args: any) => {
        if (!canRun) return
        canRun = false
        setTimeout(() => {
            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
            // @ts-ignore
            callBack.apply(this, args)
            callBack()
            canRun = true
        }, time)
    }
}

// 防抖
export function debounce(callBack: IFunc, time = 250) {
    let debounceTimer: null | number = null

    return (...args: any) => {
        if (debounceTimer) {
            clearTimeout(debounceTimer)
            debounceTimer = null
        }
        debounceTimer = setTimeout(() => {
            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
            // @ts-ignore
            callBack.apply(this, args)
            callBack()
        }, time)
    }
}
export function debouncePro(fn: IFunc, delay = 250) {
    let timeout: any = null
    return function () {
      const context = this
      const args: any = arguments
      clearTimeout(timeout)
      const callNow = !timeout
      timeout = setTimeout(() => {
        timeout = null
      }, delay)
      if (callNow) fn.apply(context, args)
    }
  }
// 校验证件号码格式：身份证|回乡证|台胞证
export function checkIDNoFormat(type, code) {
    let pass = true
    let msg = ''
    let idNumber = ''
    switch (type) {
        case 'idCard':
            if (!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(code)) {
                pass = false
                msg = '身份证格式错误!'
            } else {
                // 如果已经是大写X或者不是X，则直接返回
                if (/X$/.test(code) || code.endsWith('X')) idNumber = code
                else idNumber = code.replace(/x$/i, 'X') // 将小写的x转换为大写的X
            }
            break
        case 'gangAoPass':
            if (!/^[HMhm]{1}([0-9]{10}|[0-9]{8})$/.test(code)) {
                pass = false
                msg = '回乡证格式错误!'
            }
            break
        case 'taiwanPass':
            if (!/^\d{8}|^[a-zA-Z0-9]{10}|^\d{18}$/.test(code)) {
                pass = false
                msg = '台胞证格式错误!'
            }
            break
        default:
            console.log('请检查输入的检验类型名是否正确！')
    }
    return {
        pass,
        msg,
        idNumber,
    }
}
// 电子邮箱验证
export function checkEmailFn(email: string) {
    const reg = /^([a-zA-Z0-9]+[_|-|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|-|.]?)*[a-zA-Z0-9]+.[a-zA-Z]{2,3}$/gi
    if (!reg.test(email)) return false
    return true
}
// 银行账号只允许字母+数字
export function checkBankAccountFn(bankNumber: string) {
    const reg = /^[A-Za-z0-9]+$/
    if (!reg.test(bankNumber)) return false
    return true
}

// 手机号验证
export function checkPhoneFn(phoneNumber: string) {
    const reg = /^1[3-9]\d{9}$/
    if (!reg.test(phoneNumber)) return false
    return true
}

// 手机号脱敏
export function phoneDesensitize(phone: string) {
    return phone?.replace(phone.substring(3, 7), '****')
}

// 下载视频
const baseUrl = import.meta.env.VITE_SHOUDAO_IMG_URL
export async function downloadVideo(url: string) {
    await uni.showLoading({ title: '下载中' })
    // 1.将远程文件下载到小程序的内存中,tempFilePath
    const res = await uni.downloadFile({ url: `${baseUrl}/${url}` })
    // 2.将小程序内存中的临时文件下载到本地上
    await uni.saveVideoToPhotosAlbum({
        filePath: res.tempFilePath,
    })
    // 3.提示用户下载成功
    uni.hideLoading()
    await uni.showToast({ title: '下载成功' })
}

// 复制文本到粘贴板
export async function copyToClipboard(copyData: object) {
    uni.setClipboardData({
        data: copyData.content,
        success() {
            uni.showToast({
                title: copyData.successTip || '复制成功',
                icon: 'success',
                duration: 3000,
            })
        },
        fail: () => {
            uni.showToast({
                title: copyData.failTip || '复制失败',
                icon: 'error',
                duration: 3000,
            })
        },
    })
}

// 是否立即执行的防抖函数
export const debounceImmediate = (func, delay = 500, immediate = true) => {
    let timer
    return function (...args) {
        if (immediate && !timer) {
            func.apply(this, args)
        }
        clearTimeout(timer)
        timer = setTimeout(() => {
            timer = null
            if (!immediate) {
                func.apply(this, args)
            }
        }, delay)
    }
}
